#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
}
bool MainWindow::collectBuildOutputs(const QString& basePath,
                                     const QString& designerPath,
                                     const QString& pluginName,
                                     const QString& pluginPackPath)
{
    if(basePath.isEmpty() ||
        designerPath.isEmpty() ||
        pluginName.isEmpty() ||
        pluginPackPath.isEmpty())
    {
        tip("信息填写不完整！");
        return false;
    }

    QMap<QString, QMap<QString, QPair<QString, QString>>> hash;

    QDir rootDir(basePath);
    if (!rootDir.exists()) {
        tip("路径不存在：" + basePath);
        return false;
    }

    // 获取 .dll .lib .a 文件，同时把dll拷贝到designer中
    QFileInfoList subDirs(QDir(rootDir.filePath("build")).entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot));
    foreach (const QFileInfo& compilerDirInfo , subDirs) {
        QString dirName = compilerDirInfo.fileName().toLower();
        QString compiler;

        if (dirName.contains("msvc")) {
            compiler = MS;
        } else if (dirName.contains("mingw")) {
            compiler = MI;
        } else {
            continue;
        }

        QDir compilerDir = QDir(compilerDirInfo.absoluteFilePath());
        foreach (const QString& mode , modes) {
            QDir modeDir = QDir(compilerDir.filePath(mode));
            if (!modeDir.exists() || modeDir.entryList(QDir::Files).isEmpty()) {
                continue;
            }

            QString Path, fileName;
            QFileInfoList files = modeDir.entryInfoList(QDir::Files);
            foreach (const QFileInfo& file , files) {
                if (file.suffix() == "dll") {
                    Path = file.path();
                    fileName = file.fileName();
                    fileName = fileName.left(fileName.lastIndexOf('.'));
                    if(compiler == MS && mode == "release"){
                        if(!copy(file.absoluteFilePath(), designerPath + "/" + file.fileName())){
                            return false;
                        }
                    }
                    hash[compiler][mode] = {Path, fileName};
                    break;
                }
            }
        }
    }

    // 在这一步成功之前，不允许修改其他文件

    if(!hash[MS].contains("release")){
        tip("缺少MSVC+Release构建的dll依赖！！！");
        return false;
    }

    // 拷贝所有 .h 文件到PluginPack/Plugin1/include 中
    QStringList headFiles = rootDir.entryList(QStringList() << "*.h", QDir::Files);
    foreach(const QString& hf, headFiles){
        if(!copy(rootDir.filePath(hf),
                  QDir(pluginPackPath + "/" + pluginName + "/include").filePath(hf)))
            return false;
    }

    foreach(const QString& complier , compliers){
        if(!hash.contains(complier))continue;
        foreach(const QString& mode , modes){
            if(!hash[complier].contains(mode))continue;
            auto pair = hash[complier][mode];
            QString Path = pluginPackPath+"/"+pluginName+"/lib/" + complier + "/" + mode;
            QList<QString>list = {".dll", complier == MS ? ".lib" : ".a"};
            foreach(QString suf, list){
                QString name = (suf == ".a" ? "lib" : "") + pair.second + suf;
                if(!copy(pair.first + "/" + name, Path + "/" + name))
                    return false;
            }
        }
    }

    QString dllName = hash[MS]["release"].second;
    QString priFilePath = pluginPackPath + "/" + pluginName + "/" + pluginName +  ".pri";
    QFile priFile(priFilePath);
    if (!priFile.exists()) {
        if (priFile.open(QIODevice::WriteOnly | QIODevice::Text)) {
            QTextStream out(&priFile);
            out << Template.arg(dllName);
            priFile.close();
        }
    }

    // 8. 更新 allPri.pri
    QString allPri = pluginPackPath + "/allPri.pri";
    QFile allPriFile(allPri);
    if (!allPriFile.exists()) {
        allPriFile.open(QIODevice::WriteOnly | QIODevice::Text);
        allPriFile.close();
    }

    if (allPriFile.open(QIODevice::ReadWrite | QIODevice::Text)) {
        QTextStream in(&allPriFile);
        QString content = in.readAll();
        if (!content.contains("include(" + pluginName + "/" + pluginName + ".pri)")) {
            in.seek(allPriFile.size());
            in << "include(" << pluginName << "/" << pluginName << ".pri)\n";
        }
        allPriFile.close();
    }
    return true;
}

QString MainWindow::path()
{
    QString dir = QFileDialog::getExistingDirectory(
        this,
        "选择一个文件夹",
        "D:/Code/QtCode/Qt6/CoustomDesignerUI",
        QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks
        );
    return dir;
}

bool MainWindow::copy(const QString &file, const QString &copyFile)
{
    QFileInfo srcInfo(file);
    QFileInfo dstInfo(copyFile);
    QString targetDir = dstInfo.absolutePath();

    if (!srcInfo.exists()) {
        tip("文件不存在：" + file);
        return false;
    }

    if (!QDir().mkpath(targetDir)) {
        tip("创建目标目录失败：" + targetDir);
        return false;
    }

    QFile f(file);
    QString context = "拷贝失败：";
    if (QFile::exists(copyFile)){// 文件已存在
        if (!QFile::remove(copyFile)) {// 文件正被占用
            if(QMessageBox::question(
                    this,
                    "拷贝失败",
                    "文件可能被 Qt Creator占用，是否关闭 Qt Creator 并重试？\n（注意保存你的文件！！!）") == QMessageBox::Yes){
                needRestartQt = true;// 标记需要重启
                QProcess::execute("taskkill", {"/F", "/IM", "qtcreator.exe"});
                QThread::sleep(1);  // 给系统一点时间关闭进程
                if(!QFile::remove(copyFile)){// 再次尝试删除
                    tip("依旧拷贝失败，请检查拷贝文件是否被其他占用");
                    return false;
                }
                context = "依旧拷贝失败：";
            }
            else return false;
        }
    }
    if (!f.copy(copyFile)) {
        tip(context + file + " copy to " + copyFile + "\n原因：" + f.errorString());
        return false;
    }
    return true;
}

void MainWindow::tip(const QString &context)
{
    QMessageBox::warning(this, "tip", context);
}

MainWindow::~MainWindow()
{
    delete ui;
}


void MainWindow::on_btn_basePath_clicked()
{
    QString basePath = path();
    ui->basePath->setText(basePath);
    ui->pluginName->setText(QDir(basePath).dirName());
}


void MainWindow::on_btn_designerPath_clicked()
{
    ui->designerPath->setText(path());
}


void MainWindow::on_btn_pluginName_clicked()
{
    QString filePath = QFileDialog::getOpenFileName(this, "选择文件", "", "所有文件 (*.*)");
    if (filePath.isEmpty()) return;
    ui->pluginName->setText(QFileInfo(filePath).completeBaseName());
}


void MainWindow::on_btn_pluginPackPath_clicked()
{
    ui->pluginPackPath->setText(path());
}


void MainWindow::on_btn_packing_clicked()
{
    bool result = collectBuildOutputs(ui->basePath->text(),
                        ui->designerPath->text(),
                        ui->pluginName->text(),
                        ui->pluginPackPath->text()
                        );
    if(needRestartQt){// 无论成功与否，都重启Qt
        QProcess::startDetached("qtcreator.exe");
    }
    if(result){// 成功
        if(!needRestartQt){// 如果Qt没有关闭过，需要重启加载插件
            if(QMessageBox::question(this, "打包完成！", "是否重启Qt？") == QMessageBox::Yes){
                QProcess::execute("taskkill", {"/F", "/IM", "qtcreator.exe"});
                QThread::sleep(1);  // 给系统一点时间关闭进程
                QProcess::startDetached("qtcreator.exe");
            }
        }
        else QMessageBox::about(this, "", "打包完成！");
        close();
    }
    needRestartQt = false;
}